/*
 *  Copyright 2019-2020 Zheng Jie
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package me.zhengjie.modules.mnt.service.impl

import jakarta.persistence.criteria.CriteriaBuilder
import jakarta.persistence.criteria.CriteriaQuery
import jakarta.persistence.criteria.Root
import me.zhengjie.common.utils.PageResult
import me.zhengjie.common.utils.PageUtil
import me.zhengjie.common.utils.QueryHelp
import me.zhengjie.common.utils.ValidationUtil
import me.zhengjie.modules.mnt.util.ExecuteShellUtil
import me.zhengjie.modules.mnt.domain.ServerDeploy
import me.zhengjie.modules.mnt.repository.ServerDeployRepository
import me.zhengjie.modules.mnt.service.ServerDeployService
import me.zhengjie.modules.mnt.service.dto.ServerDeployDto
import me.zhengjie.modules.mnt.service.dto.ServerDeployQueryCriteria
import me.zhengjie.modules.mnt.service.mapstruct.ServerDeployMapper
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.domain.Specification
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.io.IOException
import java.util.function.Supplier
import jakarta.servlet.http.HttpServletResponse
import me.zhengjie.common.utils.FileUtil
/**
 * @author zhanghouying
 * @date 2019-08-24
 */
@Service
class ServerDeployServiceImpl (
    private val serverDeployRepository: ServerDeployRepository? = null,
    private val serverDeployMapper: ServerDeployMapper? = null
) : ServerDeployService {
    override fun queryAll(criteria: ServerDeployQueryCriteria?, pageable: Pageable?): PageResult<ServerDeployDto?> {
        val page: Page<ServerDeploy> = serverDeployRepository!!.findAll(
            Specification { root: Root<ServerDeploy?>?, criteriaQuery: CriteriaQuery<*>?, criteriaBuilder: CriteriaBuilder? ->
                QueryHelp.getPredicate(
                    root!!,
                    criteria,
                    criteriaBuilder!!
                )
            }, pageable!!) as Page<ServerDeploy>
        return PageUtil.toPage(page.map{ serverDeployMapper!!.toDto(it) }) as PageResult<ServerDeployDto?>
    }

    override fun queryAll(criteria: ServerDeployQueryCriteria?): List<ServerDeployDto?> {
        return serverDeployMapper!!.toDto(serverDeployRepository!!.findAll(Specification { root: Root<ServerDeploy?>?, criteriaQuery: CriteriaQuery<*>?, criteriaBuilder: CriteriaBuilder? ->
            QueryHelp.getPredicate(
                root!!,
                criteria,
                criteriaBuilder!!
            )
        }))!!
    }

    override fun findById(id: Long?): ServerDeployDto {
        val server: ServerDeploy = serverDeployRepository!!.findById(id!!).orElseGet(Supplier { ServerDeploy() })!!
        ValidationUtil.isNull(server.id, "ServerDeploy", "id", id)
        return serverDeployMapper!!.toDto(server)!!
    }

    override fun findByIp(ip: String?): ServerDeployDto {
        val deploy: ServerDeploy = serverDeployRepository!!.findByIp(ip)!!
        return serverDeployMapper!!.toDto(deploy)!!
    }

    override fun testConnect(resources: ServerDeploy): Boolean {
        var executeShellUtil: ExecuteShellUtil? = null
        return try {
            executeShellUtil = ExecuteShellUtil(
                resources.ip,
                resources.account,
                resources.password,
                resources.port!!
            )
            executeShellUtil.execute("ls") == 0
        } catch (e: Exception) {
            false
        } finally {
            if (executeShellUtil != null) {
                executeShellUtil.close()
            }
        }
    }

    @Transactional(rollbackFor = [Exception::class])
    override fun create(resources: ServerDeploy?) {
        serverDeployRepository!!.save<ServerDeploy>(resources!!)
    }

    @Transactional(rollbackFor = [Exception::class])
    override fun update(resources: ServerDeploy) {
        val serverDeploy: ServerDeploy = serverDeployRepository!!.findById(resources.id!!).orElseGet(
            Supplier { ServerDeploy() })!!
        ValidationUtil.isNull(serverDeploy.id, "ServerDeploy", "id", resources.id!!)
        serverDeploy.copy(resources)
        serverDeployRepository.save<ServerDeploy>(serverDeploy)
    }

    @Transactional(rollbackFor = [Exception::class])
    override fun delete(ids: Set<Long?>) {
        for (id in ids) {
            serverDeployRepository!!.deleteById(id!!)
        }
    }

    @Throws(IOException::class)
    override fun download(queryAll: List<ServerDeployDto?>, response: HttpServletResponse?) {
        val list: MutableList<Map<String?, Any?>> = ArrayList()
        for (deployDto in queryAll) {
            val map: MutableMap<String?, Any?> = LinkedHashMap()
            map["服务器名称"] = deployDto!!.name!!
            map["服务器IP"] = deployDto.ip!!
            map["端口"] = deployDto.port!!
            map["账号"] = deployDto.account!!
            map["创建日期"] = deployDto.createTime!!
            list.add(map)
        }
        FileUtil.downloadExcel(list, response!!)
    }
}